package nl.hanze.shoestring.ui;

import com.toedter.calendar.JDateChooser;
import com.toedter.calendar.JTextFieldDateEditor;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import nl.hanze.shoestring.domain.Deelnemer;
import nl.hanze.shoestring.domain.Reservering;
import nl.hanze.shoestring.logic.Logic;
import nl.hanze.shoestring.logic.Rules;
import nl.hanze.shoestring.logic.Utils;

/**
 * ReserveringPanel ReserveringPanel is de GUI waarin de Reserveringen kunnen
 * worden opgevraagd en bewerkt.
 *
 * @author henk
 */
public class ReserveringPanel extends JPanel {

    private static final long serialVersionUID = 1L;
    Logic logic;
    JPanel pQueryInput, pRecord, pNavigation, pDbGrid, pDbDeelnemerGrid, pNavigationDeelnemer, cardReservering;
    JLabel lblZoekSleutel, lblBeginDatum, lblEindDatum, lblId, lblPlId, lblDatumBoeking, lblAantalDeelnemers;
    JLabel lblDatumAnulering, lblBedrag, lblBetaald, lblPlReisNaam, lblKlantNaam, lblKlantGebDat, lblMaxAantalDeelnemers;
    JTextField txtZoekSleutel, txtId, txtPlId, txtAantalDeelnemers;
    JTextField txtBedrag, txtPlReisNaam, txtKlantNaam, txtKlantGebDat;
    JButton butZoeken, butSave, butAnnuleer, butDeelnemers, butRefresh;
    JDateChooser calBeginDatum, calEindDatum, calDatumBoeking, calDatumAnulering;
    JCheckBox chkBetaald;
    JTable table, tableDeelnemer;
    JScrollPane scrollPaneRes, scrollPaneDeelnemer;
    DefaultTableModel model, modelDeelnemer;
    Reservering resObj = null;
    Deelnemer deelnemerObj = null;
    int heightField = 25;
    int numberOfRows = 10;
    int numberOfRowsDeelnemer = 10;
    List<Reservering> reserveringList;
    List<Deelnemer> deelnemerList;
    final DeelnemerPanel deelnemerPanel;
    Color lightred = new Color(245, 150, 160);
    Color lightgreen = new Color(145, 225, 150);

    public ReserveringPanel(Logic logic, final JPanel cardReservering, final DeelnemerPanel deelnemerPanel) {
        this.logic = logic;
        this.cardReservering = cardReservering;
        this.deelnemerPanel = deelnemerPanel;
        deelnemerPanel.setReserveringPanel(this);

        table = new JTable();
        tableDeelnemer = new JTable();
        setLayout(new BorderLayout(20, 20));

        // input velden north sectie (Zoeken)
        pQueryInput = new JPanel();
        pQueryInput.setLayout(null);
        pQueryInput.setPreferredSize(new Dimension(400, 110));

        lblZoekSleutel = UIHelper.createLabel(lblZoekSleutel = new JLabel(), "Zoeksleutel klanten", 10, 10, 150, heightField, pQueryInput);
        txtZoekSleutel = UIHelper.createTextField(txtZoekSleutel = new JTextField(), "", 170, 10, 250, heightField, pQueryInput);

        txtZoekSleutel.addKeyListener(new KeyAdapter() {

            @Override
            public void keyReleased(KeyEvent e) {
                searchReservering();
            }
        });

        butZoeken = UIHelper.createButton(butZoeken = new JButton(), "Zoeken", 430, 10, 100, heightField, pQueryInput);
        butZoeken.addActionListener(
                new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        searchReservering();
                    }
                });

        lblBeginDatum = UIHelper.createLabel(lblBeginDatum = new JLabel(), "Begindatum", 10, 40, 150, heightField, pQueryInput);
        calBeginDatum = UIHelper.createDateChooser(calBeginDatum = new JDateChooser(), null, 170, 40, 150, heightField, pQueryInput);

        calBeginDatum.addPropertyChangeListener(new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent pce) {
                searchReservering();
            }
        });

        lblEindDatum = UIHelper.createLabel(lblEindDatum = new JLabel(), "Einddatum", 10, 70, 150, heightField, pQueryInput);
        calEindDatum = UIHelper.createDateChooser(calEindDatum = new JDateChooser(), null, 170, 70, 150, heightField, pQueryInput);

        calEindDatum.addPropertyChangeListener(new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent pce) {
                searchReservering();
            }
        });

        // Center sectie, database record (details)
        pRecord = new JPanel();
        pRecord.setLayout(null);
        pRecord.setPreferredSize(new Dimension(500, 500));
        pRecord.setBorder(BorderFactory.createLineBorder(Color.blue));

        lblId = UIHelper.createLabel(lblId = new JLabel(), "Id", 20, 10, 150, heightField, pRecord);
        txtId = UIHelper.createTextField(txtId = new JTextField(), "", 170, 10, 100, heightField, pRecord);

        lblPlReisNaam = UIHelper.createLabel(lblPlReisNaam = new JLabel(), "Reisnaam", 20, 40, 150, heightField, pRecord);
        txtPlReisNaam = UIHelper.createTextField(txtPlReisNaam = new JTextField(), "", 170, 40, 290, heightField, pRecord);

        lblDatumBoeking = UIHelper.createLabel(lblDatumBoeking = new JLabel(), "Datum Boeking", 20, 70, 150, heightField, pRecord);
        calDatumBoeking = UIHelper.createDateChooser(calDatumBoeking = new JDateChooser(), null, 170, 70, 150, heightField, pRecord);

        lblDatumAnulering = UIHelper.createLabel(lblDatumAnulering = new JLabel(), "Datum Annulering", 20, 100, 150, heightField, pRecord);
        calDatumAnulering = UIHelper.createDateChooser(calDatumAnulering = new JDateChooser(), null, 170, 100, 150, heightField, pRecord);

        lblBedrag = UIHelper.createLabel(lblBedrag = new JLabel(), "Bedrag", 20, 130, 150, heightField, pRecord);
        txtBedrag = UIHelper.createTextField(txtBedrag = new JTextField(), "", 170, 130, 150, heightField, pRecord);

        lblBetaald = UIHelper.createLabel(lblBetaald = new JLabel(), "Betaald", 20, 160, 150, heightField, pRecord);
        chkBetaald = UIHelper.createCheckBox(chkBetaald = new JCheckBox(), "", 170, 160, 150, heightField, pRecord);

        lblAantalDeelnemers = UIHelper.createLabel(lblAantalDeelnemers = new JLabel(), "Aantal deelnemers", 20, 190, 150, heightField, pRecord);
        txtAantalDeelnemers = UIHelper.createTextField(txtAantalDeelnemers = new JTextField(), "", 170, 190, 50, heightField, pRecord);
        lblMaxAantalDeelnemers = UIHelper.createLabel(lblAantalDeelnemers = new JLabel(), "", 230, 190, 150, heightField, pRecord);

                // buttons
                butSave = UIHelper.createButton(butSave = new JButton(), "Opslaan", 170, 220, 120, heightField, pRecord);
                butSave.addActionListener(
                        new ActionListener() {
                            @Override
                            public void actionPerformed(ActionEvent e) {
                                if(resObj!=null) {
                                    updateRecord(resObj);
                                } else {
                                    addRecord();
                                }
                            }
                        });

                butAnnuleer = UIHelper.createButton(butAnnuleer = new JButton(), "Annuleren", 350, 220, 120, heightField, pRecord);
                butAnnuleer.addActionListener(
                        new ActionListener() {
                            @Override
                            public void actionPerformed(ActionEvent e) {
                                // Rule W005
                                if(!Rules.checkReisAnnuleringDate(resObj)) {
                                    Utils.errorMessage(pRecord, "Validatiefout", "W005 - Annuleringsdatum > start reis");
                                }
                                // rule W006
                                else if(!Rules.checkReisAnnuleringDatumNaBoekingsDatum(resObj, Calendar.getInstance().getTime())) {
                                    Utils.errorMessage(pRecord, "Validatiefout", "W006 - Annuleringsdatum > boekingsdatum");
                                } else {
                                    annuleerReservering();
                                }
                        }});

                // Switch naar Deelnemer Panel (Toevoegen)
                butDeelnemers = UIHelper.createButton(butDeelnemers = new JButton(), "Deelnemer toevoegen", 240, 260, 160, heightField, pRecord);
                butDeelnemers.addActionListener(
                        new ActionListener() {
                            @Override
                            public void actionPerformed(ActionEvent e) {
                                if(resObj!=null) {
                                    // pass reference Reservering
                                    deelnemerPanel.setSelectedReservering(resObj);
                                    switchPanel("D");
                                }
                        }});

                // refresh na wijzigingen Planning
                butRefresh = UIHelper.createButton(butRefresh = new JButton(), "", 470, 40, 30, heightField, pRecord);
                butRefresh.setIcon(new ImageIcon("src/nl/hanze/shoestring/ui/graphics/refresh.png"));
                butRefresh.addActionListener(
                        new ActionListener() {
                            @Override
                            public void actionPerformed(ActionEvent e) {
                                updateTable(true);
                                emptyAll();
                        }});
                
                
        // fill tab pane
        add(pRecord, BorderLayout.WEST);
        add(pQueryInput, BorderLayout.NORTH);
        addTable();
        addDeelnemerTable();
        emptyAll();
    }

    /**
     * Haal informatie uit database en toon in JTable
     */
    private void addTable() {

        // Gridcontainer
        pDbGrid = new JPanel(new BorderLayout(2, 3));

        // scroll pane eigenschappen
        scrollPaneRes = new JScrollPane(table);
        Dimension d = table.getPreferredSize();
        scrollPaneRes.setPreferredSize(new Dimension(d.width, table.getRowHeight() * numberOfRows));

        // navigatie container
        UIHelper.addNavigation(pNavigation = new JPanel(), table, scrollPaneRes, numberOfRows);

        // kolom eigenschappen - breedte
        Object[] headers = {"Nummer", "Reisnaam", "Datum boeking", "Datum reis", "Datum annulering", "Bedrag", "Betaald", "Min#", "Max#", "MinLft", "MaxLft"};
        int[] breedte = {50, 300, 100, 100, 110, 60, 50, 50, 50, 50, 50};

        // tablemodel en eigenschappen instellen, kolombreedte etc
        model = new DefaultTableModel(headers, 0) {

            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }

            // rendering van cellen, toont checkbox en juiste datum indien datatype overeenkomstig is
            // null velden veroorzaken fout, standaard maar op String gezet beahalve date kolom
            @Override
            public Class getColumnClass(int column) {
                try {
                    return getValueAt(0, column).getClass();
                } catch (java.lang.NullPointerException e) {
                    if (column == 3) {
                        return Date.class;
                    } else {
                        return String.class;
                    }
                }
            }
        };

        table.setModel(model);
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        for (int i0 = 0; i0 < breedte.length; i0++) {
            table.getColumnModel().getColumn(i0).setPreferredWidth(breedte[i0]);
        }

        // vul JTable (Overzicht) met lijst -Reserveringen-
        updateTable(true);

        // selecteer row door muisklik , bewaar gerelateerd Reservering Object   
        table.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent e) {
                resObj = reserveringList.get(table.convertRowIndexToModel(table.getSelectedRow()));
                getRecord(resObj);
            }
        });

        pDbGrid.add(scrollPaneRes, BorderLayout.CENTER);
        pDbGrid.add(pNavigation, BorderLayout.SOUTH);
        add(pDbGrid, BorderLayout.SOUTH);
    }

    /*
     * Vul detailvelden met geselecteerde rowdata
     */
    public void getRecord(Reservering resObj) {
        txtId.setText("" + resObj.getId());
        txtId.setEditable(false);
        txtPlReisNaam.setText("" + resObj.getPlanningId().getReisId().getNaam());
        txtPlReisNaam.setEditable(false);
        calDatumBoeking.setDate(resObj.getDatumBoeking());
        calDatumAnulering.setDate(resObj.getDatumAnnulering());
        txtBedrag.setText("" + Utils.getValutaFormatFromNumber(resObj.getBedrag()));
        chkBetaald.setSelected(resObj.getBetaald());

        // update deelnemers
        updateTableDeelnemer(true, resObj);
        txtAantalDeelnemers.setText("" + logic.getAantalDeelnemers(resObj));
        lblMaxAantalDeelnemers.setText("Maximum : " + Rules.getMaxAantalDeelnemersReservering(resObj));

        // werk -onderliggend- deelnemerpanel bij
        deelnemerPanel.setSelectedReservering(resObj);

        // scherm controls
        checkMaximumAantalDeelnemers();
        checkReserveringGeannulleerd(resObj);
    }

    /*
     * update detailvelden in database
     */
    private void updateRecord(Reservering resObj) {
        resObj.setDatumBoeking(calDatumBoeking.getDate());
        resObj.setDatumAnnulering(calDatumAnulering.getDate());
        resObj.setBedrag(Utils.getFloatValueOrNull(txtBedrag.getText()));
        resObj.setBetaald(chkBetaald.isSelected() == true);

        logic.updateReservering(resObj);
        updateTable(true);
        emptyAll();
    }

    /**
     * update reisprijs na toevoegen deelnemer
     *
     * @param resObj Reservering
     */
    public void updateReisPrijs(Reservering resObj) {
        resObj.setBedrag(Utils.getFloatValueOrNull("" + logic.getTotaleReisPrijs(resObj)));
        logic.updateReservering(resObj);
        updateTable(true);
    }

    /*
     * voeg record toe aan database
     */
    private void addRecord() {
        resObj = new Reservering();
        resObj.setDatumBoeking(calDatumBoeking.getDate());
        resObj.setDatumAnnulering(calDatumAnulering.getDate());
        resObj.setBedrag(Utils.getFloatValueOrNull(txtBedrag.getText()));
        resObj.setBetaald(chkBetaald.isSelected() == true);

        logic.updateReservering(resObj);
        updateTable(true);
        emptyAll();
    }

    /*
     * delete record
     */
    private void deleteRecord(Reservering resObj) {
        logic.deleteReservering(resObj);
        updateTable(true);
        emptyAll();

    }

    /*
     * Annuleer Reservering
     */
    private void annuleerReservering() {
        calDatumAnulering.setDate(Calendar.getInstance().getTime());
        calDatumAnulering.setEnabled(false);
        txtBedrag.setEnabled(false);
        chkBetaald.setEnabled(false);
    }

    /*
     * Zoek reservering
     */
    private void searchReservering() {
        String name = txtZoekSleutel.getText();
        Date startDate = calBeginDatum.getDate();
        Date endDate = calEindDatum.getDate();

        reserveringList = logic.searchReservering(name, startDate, endDate);
        updateTable(false);
    }

    /**
     * update overzicht Reserveringen JTable
     *
     * @param refresh
     */
    public void updateTable(Boolean refresh) {
        // data in JTable plaatsen
        if (refresh) {
            if(reserveringList!=null) {
                reserveringList.clear();
            }
            reserveringList = logic.getReserveringList();
        }
        model.setRowCount(0);

        for (Reservering reservering : reserveringList) {
            Object[] o = {reservering.getId(),
                reservering.getPlanningId().getReisId().getNaam(),
                reservering.getDatumBoeking(),
                reservering.getPlanningId().getDatumVan(),
                reservering.getDatumAnnulering(),
                reservering.getBedrag(),
                reservering.getBetaald(),
                reservering.getPlanningId().getAantalMinimum(),
                reservering.getPlanningId().getAantalMaximum(),
                reservering.getPlanningId().getMinimumLeeftijd(),
                reservering.getPlanningId().getMaximumLeeftijd()
            };
            model.addRow(o);
        }
    }

    /**
     * initialiseer alle velden
     */
    private void emptyAll() {
        txtId.setText("");
        txtId.setEditable(false);
        txtPlReisNaam.setText("");
        txtPlReisNaam.setEditable(false);
        calDatumBoeking.setDate(null);
        calDatumBoeking.setEnabled(false);
        ((JTextFieldDateEditor) calDatumBoeking.getDateEditor()).setDisabledTextColor(Color.black);
        calDatumAnulering.setEnabled(false);
        calDatumAnulering.setDate(null);
        ((JTextFieldDateEditor) calDatumAnulering.getDateEditor()).setDisabledTextColor(Color.black);
        txtBedrag.setText("");
        chkBetaald.setSelected(false);
        txtBedrag.setEditable(false);
        chkBetaald.setEnabled(true);
        txtAantalDeelnemers.setText("");
        txtAantalDeelnemers.setEditable(false);
        lblMaxAantalDeelnemers.setText("Maximum : ");
        resObj = null;
        // deelnemerPanel bijwerken
        deelnemerPanel.setSelectedReservering(resObj);

        butDeelnemers.setBackground(lightred);
    }

    /**
     * Check maximum aantal deelnemers aan reis pas scherm controls aan dmv rode
     * en groene kleur
     */
    private void checkMaximumAantalDeelnemers() {
        if (Rules.checkMaxAantalDeelnemers(resObj)) {
            txtAantalDeelnemers.setBackground(lightred);
            butDeelnemers.setBackground(lightred);
            butDeelnemers.setEnabled(false);
        } else {
            txtAantalDeelnemers.setBackground(lightgreen);
            butDeelnemers.setBackground(lightgreen);
            butDeelnemers.setEnabled(true);
        }

    }

    /**
     *
     * Check of reservering is geannuleerd pas scherm controls aan dmv
     * rood/groen
     */
    private void checkReserveringGeannulleerd(Reservering resObj) {

        if (Rules.isReserveringGeannuleerd(resObj)) {
            butDeelnemers.setBackground(lightred);
            butDeelnemers.setEnabled(false);
            calDatumAnulering.setEnabled(false);
        }
    }
    

    /**
     * ===========================Deelnemer subpane=============================
     *
     * Voeg de deelnemer (sub)pane toe: (EAST sectie) Deelemers behorend bij
     * geselecteerde reservering
     *
     */
    private void addDeelnemerTable() {

        // Gridcontainer
        pDbDeelnemerGrid = new JPanel(new BorderLayout(2, 3));
        pDbDeelnemerGrid.setPreferredSize(new Dimension(500, 500));
        pDbDeelnemerGrid.setBorder(BorderFactory.createLineBorder(Color.blue));

        // scroll pane eigenschappen
        scrollPaneDeelnemer = new JScrollPane(tableDeelnemer);
        Dimension d2 = tableDeelnemer.getPreferredSize();
        scrollPaneDeelnemer.setPreferredSize(new Dimension(d2.width, tableDeelnemer.getRowHeight() * numberOfRowsDeelnemer));

        // navigatie container
        UIHelper.addNavigation(pNavigationDeelnemer = new JPanel(), tableDeelnemer, scrollPaneDeelnemer, numberOfRowsDeelnemer);

        // kolom eigenschappen - breedte
        Object[] headersDeelnemer = {"Naam", "GebDatum", "Bedrag", "Dieet", "Verlenging"};
        int[] breedteDeelnemer = {180, 90, 80, 70, 100};

        // tablemodel en eigenschappen instellen, kolombreedte etc
        modelDeelnemer = new DefaultTableModel(headersDeelnemer, 0) {

            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }

            // rendering van cellen, toont checkbox en juiste datum indien datatype overeenkomstig is
            // null velden veroorzaken fout, standaard maar op String gezet....
            @Override
            public Class getColumnClass(int column) {
                try {
                    return getValueAt(0, column).getClass();
                } catch (java.lang.NullPointerException e) {
                    return String.class;
                }
            }
        };

        tableDeelnemer.setModel(modelDeelnemer);
        tableDeelnemer.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        for (int i0 = 0; i0 < breedteDeelnemer.length; i0++) {
            tableDeelnemer.getColumnModel().getColumn(i0).setPreferredWidth(breedteDeelnemer[i0]);
        }

        // vul JTable met -Deelnemer- obj lijst
        updateTableDeelnemer(true, resObj);

        // selecteer row door muisklik en retourneer DeelnemerObject   
        tableDeelnemer.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent e) {
                deelnemerObj = deelnemerList.get(tableDeelnemer.convertRowIndexToModel(tableDeelnemer.getSelectedRow()));
                getDeelnemerRecord(deelnemerObj);
            }
        });

        pDbDeelnemerGrid.add(scrollPaneDeelnemer, BorderLayout.CENTER);
        pDbDeelnemerGrid.add(pNavigationDeelnemer, BorderLayout.SOUTH);
        add(pDbDeelnemerGrid, BorderLayout.EAST);

    }

    public void updateTableDeelnemer(Boolean refresh, Reservering resObj) {
        // data in JTable plaatsen
        modelDeelnemer.setRowCount(0);

        if (refresh && resObj != null) {
            deelnemerList = resObj.getDeelnemerList();
        }

        if (deelnemerList != null) {
            for (Deelnemer deelnemer : deelnemerList) {
                Object[] o = {deelnemer.getKlantId().getPersoon().getAchternaam(),
                    deelnemer.getKlantId().getPersoon().getGeboortedatum(),
                    deelnemer.getBedrag(),
                    deelnemer.getDieet(),
                    deelnemer.getVerlenging()
                };
                modelDeelnemer.addRow(o);
            }
        }
    }

    /**
     * pass geselecteerde Deelnemer naar DeelnemerPanel en switch naar dit
     * scherm met Deelnemer reord ingevuld
     *
     * @param Deelnemer
     */
    private void getDeelnemerRecord(Deelnemer deelnemer) {
        deelnemerPanel.setSelectedDeelnemer(deelnemerObj);
        switchPanel("D");
    }

    /**
     * switch naar panel Deelnemer
     *
     * @param string cardlayout reference
     */
    private void switchPanel(String card) {
        CardLayout c1 = (CardLayout) (cardReservering.getLayout());
        c1.show(cardReservering, card);
    }
}
